package common

import (
	"MoSkeleton/framework"
	"MoSkeleton/framework/core/consts"
	"MoSkeleton/framework/core/moerrors"
	"MoSkeleton/framework/utils"
	"fmt"
	"github.com/samber/lo"
	"io"
	"mime/multipart"
	"os"
	"path/filepath"
)

type CommonService struct {
}

func (cs *CommonService) UploadFile(file *multipart.FileHeader) (string, error) {
	return cs.UploadFileWithExtensions(cs.GetUploadBasePath(), "", file, &consts.DEFAULT_ALLOWED_EXTENSION)
}

func (cs *CommonService) UploadFileWithExtensions(basePath string, browserPrefixPath string, file *multipart.FileHeader, extensions *[]string) (string, error) {
	if err := cs.checkAllows(file, extensions); err != nil {
		return "", err
	}
	newFilename := cs.extractFilename(file)
	if len(browserPrefixPath) > 0 {
		newFilename = filepath.Join(browserPrefixPath, newFilename)
	}
	absFile := filepath.Join(basePath, newFilename)
	if err := os.MkdirAll(filepath.Dir(absFile), os.ModePerm); err != nil {
		return "", err
	}
	src, err := file.Open()
	if err != nil {
		return "", err
	}
	defer src.Close()
	out, err := os.Create(absFile)
	if err != nil {
		return "", err
	}
	defer out.Close()

	_, err = io.Copy(out, src)
	browserFilename := filepath.Join(framework.ConfigContainerInst.AppProperty.App.Gin.Multipart.BrowserUploadPath, newFilename)
	return browserFilename, err
}

func (cs *CommonService) extractFilename(file *multipart.FileHeader) string {
	ext := filepath.Ext(file.Filename)
	return fmt.Sprintf("%s%c%s_%s%s", utils.DatePath(), filepath.Separator, file.Filename[0:len(file.Filename)-len(ext)], lo.RandomString(10, lo.LettersCharset), ext)
}

func (cs *CommonService) checkAllows(file *multipart.FileHeader, extensions *[]string) error {
	filenameLen := len(file.Filename)
	maxFilenameLen := utils.ConvertInt64(framework.ConfigContainerInst.AppProperty.App.Gin.Multipart.MaxFileSize, consts.Max_Upload_Filename_Length)
	if int64(filenameLen) > maxFilenameLen {
		return moerrors.NewValidateError(consts.FilesUploadFailCode, "文件名称不能超过"+string(maxFilenameLen)+"个字符")
	}
	ext, err := utils.GetFileExtension(file)
	if err != nil {
		return moerrors.NewValidateError(consts.FilesUploadFailCode, "文件格式不正确")
	}
	if !lo.Contains(*extensions, ext[1:]) {
		return moerrors.NewValidateError(consts.FilesUploadFailCode, "文件格式不正确")
	}
	return nil
}

func (cs *CommonService) GetUploadBasePath() string {
	uploadPath := framework.ConfigContainerInst.AppProperty.App.Gin.Multipart.AbsoluteUploadPath
	if len(uploadPath) > 0 {
		return uploadPath
	}
	uploadPath = framework.ConfigContainerInst.AppProperty.App.Gin.Multipart.UploadPath
	if len(uploadPath) > 0 {
		return filepath.Join(framework.WorkDir, uploadPath)
	}
	return filepath.Join(framework.WorkDir, consts.Default_Upload_Dir)
}
